모듈 시스템과 가시성 (mod, pub, pub use)

NOTE

GlueSQL의 core 크레이트는 수십 개의 하위 모듈로 구성되어 있지만, 사용자는 gluesql_core::prelude::* 하나만 use하면 필요한 타입을 전부 가져올 수 있음. 이는 mod/pub/pub use를 조합한 모듈 설계 덕분.

📌 개념

크레이트 최상위 모듈 구성

// core/src/lib.rs:1-36 (일부 축약)
#![deny(clippy::str_to_string)]
 
// re-export
pub use {chrono, sqlparser};
 
mod glue;
mod mock;
mod result;
 
pub mod ast;
pub mod data;
pub mod executor;
pub mod parse_sql;
pub mod plan;
pub mod query_builder;
pub mod row_conversion;
pub mod store;
pub mod translate;
 
pub mod prelude {
    pub use crate::{
        ast::DataType,
        data::{Key, Value},
        executor::{Payload, PayloadVariable, execute},
        glue::Glue,
    };
}
 
pub mod error {
    pub use crate::result::*;
}
  • mod glue; (앞에 pub 없음): 이 모듈은 크레이트 내부에서만 접근 가능. 외부 사용자는 gluesql_core::glue::...로 직접 접근할 수 없음
  • pub mod ast;: 이 모듈은 크레이트 밖에서도 gluesql_core::ast::...로 접근 가능
  • pub mod prelude { pub use crate::{...}; }: 여기저기 흩어진 핵심 타입들(Glue, Value, execute 등)을 한 곳에 모아 재수출(re-export). 사용자는 use gluesql_core::prelude::*; 한 줄로 자주 쓰는 타입을 전부 가져올 수 있음 — 내부 모듈 구조(glue::Glue가 실제로는 비공개 모듈에 있다는 사실)를 몰라도 됨
  • pub use {chrono, sqlparser};: 의존 크레이트 자체를 재수출 — 사용자가 chrono를 별도로 Cargo.toml에 추가하지 않고도 gluesql_core::chrono로 바로 사용 가능

하위 모듈에서의 선택적 재수출

// core/src/store.rs:1-27 (일부 축약)
mod alter_table;
mod function;
mod index;
mod metadata;
mod planner;
mod transaction;
 
pub trait GStore: Store + Index + Metadata + CustomFunction {}
 
pub use {
    alter_table::{AlterTable, AlterTableError},
    function::{CustomFunction, CustomFunctionMut},
    index::{Index, IndexError, IndexMut},
    metadata::{MetaIter, Metadata},
    planner::Planner,
    transaction::Transaction,
};
  • mod alter_table; 등 각 하위 모듈 파일(alter_table.rs)은 비공개로 선언
  • 하지만 그 안의 AlterTable, AlterTableError 같은 필요한 타입만 골라서 pub use로 다시 내보냄
  • 결과적으로 외부에서는 gluesql_core::store::AlterTable로 접근하지만, 실제 정의 파일(store/alter_table.rs)의 존재는 몰라도 됨 → 내부 파일 구조를 자유롭게 리팩터링해도 외부 API(경로)는 그대로 유지할 수 있는 캡슐화 기법

NOTE

C의 헤더 파일(.h)과의 차이 C에서는 .h 파일에 선언을 나열하고 #include로 가져오는 방식이라, 내부 구현 파일 이름이 곧 외부에 노출되는 경로와 밀접하게 얽히기 쉽다. Rust는 mod(비공개 파일 구조)와 pub use(공개 API 경로)를 분리할 수 있어서, 실제 폴더/파일 구조를 바꿔도 사용자가 use하는 경로(prelude::Glue 등)는 그대로 유지할 수 있음.

🔗 참고